package com.theyeasy.dvmini.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.testng.util.Strings;
import org.theyeasy.weixin.util.WxMiniUtil;

import com.alibaba.fastjson.JSONObject;
import com.theyeasy.dvmini.enums.ChatLogReplyType;
import com.theyeasy.dvmini.model.Fans;
import com.theyeasy.dvmini.model.Sales;
import com.theyeasy.dvmini.model.WebSockMsg;
import com.theyeasy.dvmini.service.ChatLogService;
import com.theyeasy.dvmini.service.DvminiSocketService;
import com.theyeasy.dvmini.service.FansService;
import com.theyeasy.dvmini.service.SalesService;
import com.theyeasy.dvmini.socket.PcWebSocketHandler;
import com.theyeasy.dvmini.socket.TopicSender;
import com.theyeasy.dvmini.util.DateUtil;
import com.theyeasy.dvmini.util.QQFaceUtil;
import com.theyeasy.dvmini.util.RedisUtil;
import com.theyeasy.dvmini.vo.Vo_msg;

@Service
public class DvminiSocketServiceImpl implements DvminiSocketService {

	private final static int CACHE_SIZE = 100;
	private final static int CHATVIEW_SIZE = 20;
	@Resource
	TopicSender topicSender;
	@Autowired
	RedisTemplate<String, String> redisTemplate;

	@Autowired
	RedisTemplate<String, Integer> redisTemplate2;

	@Autowired
	ChatLogService chatLogService;

	@Autowired
	FansService fansService;

	@Autowired
	SalesService salesService;

	@Override
	public void pushChatList(WebSockMsg msg) {
		String key = createChatViewListKey(msg);
		String fansid = msg.getFansid() + "";
		ListOperations<String, String> opsForList = redisTemplate.opsForList();
		Long size = opsForList.size(key);
		if (size > CHATVIEW_SIZE) {
			opsForList.rightPopAndLeftPush(key, fansid + "");
		} else {
			opsForList.leftPush(key, fansid + "");
		}
		List<String> range = opsForList.range(key, 1, -1);
		boolean contains = range.contains(fansid + "");
		if (contains) {
			range.remove(fansid);
		}
		opsForList.leftPush(key, fansid + "");

	}

	@Override
	public Set<Integer> popChatList(WebSockMsg msg) {
		String key = createChatViewListKey(msg);
		ListOperations<String, String> opsForList = redisTemplate.opsForList();
		List<String> range = opsForList.range(key, 1, -1);
		Set<Integer> collect = range.stream().map(e -> Integer.parseInt(e)).collect(Collectors.toSet());
		return collect;
	}

	@Override
	public void recevice(WebSockMsg msg) {

		pushChatList(msg);
		msg.setAsktime(new Date());
		String key = createKey(msg);

		if (!msg.isReaded()) {
			Fans fans = fansService.getFansById(msg.getFansid());
			msg.setNickname(fans.getNickname());
			msg.setLogo(fans.getLogo());
			Integer replytype = msg.getReplytype();
			if (replytype == null || replytype == 0) {
				msg.setReplytype(ChatLogReplyType.客户文本.getIndex());
			} else if (replytype == ChatLogReplyType.客户图片.getIndex()) {
				msg.setImgurl(msg.getImgurl() + "?" + RandomUtils.nextInt());
			}

			try {
				chatLogService.insertChatLog(msg);
				pushMsgCache(msg, key);

			} catch (Exception e) {
				e.printStackTrace();
			}

			topicSender.send("dvmini.topic", msg.toJson());

		} else {

			Fans fans = fansService.getFansById(msg.getFansid());

			if (fans == null) {
				msg.setReplytype(ChatLogReplyType.提示信息.getIndex());
				msg.setReply("粉丝不存在");
				topicSender.send("dvmini.topic", msg.toJson());
				return;
			}

			msg.setAsktime(new Date());
			msg.setReadTime(new Date());
			String sendCustomMsgText = null;
			if (msg.getReplytype() == ChatLogReplyType.销售图片.getIndex()) {
				String imgurl2 = msg.getImgurl2();

				String string = imgurl2.replace("mini.weiyisz.com/dvmini",
						System.getProperty("user.dir") + "/webapps/dvmini/WEB-INF");
				System.out.println("图片绝对路径：" + string);
				Vo_msg imgMsg = WxMiniUtil.uploadImage(string, true);
				String media_id = imgMsg.data.toString();
				sendCustomMsgText = WxMiniUtil.sendCustomMsgImg(fans.getMiniopenid(), media_id);
			} else {
				sendCustomMsgText = WxMiniUtil.sendCustomMsgText(fans.getMiniopenid(), msg.getReply());
			}

			JSONObject json = JSONObject.parseObject(sendCustomMsgText);
			Integer integer = json.getInteger("errcode");
			if (integer != null && integer != 0) {
				// 微信错误码返回
				log.error("发送小程序消息失败" + integer);
				msg.setReplytype(integer);
				msg.setReaded(false);
			} else {

				msg.setReplytype(ChatLogReplyType.人工客服.getIndex());
				chatLogService.insertChatLog(msg);
				cleanCache(msg, false);
			}
			topicSender.send("dvmini.topic", msg.toJson());
		}
	}

	private String createKey(WebSockMsg msg) {
		return CHATLOG + msg.getFansid() + "-" + msg.getSalesid() + "@" + DateUtil.formatMonth(new Date());
	}

	private String createChatViewListKey(WebSockMsg msg) {
		return CHATVIEWLIST + msg.getSalesid() + "_ids";
	}

	private void pushMsgCache(WebSockMsg msg, String key) {
		ListOperations<String, String> opsForList = redisTemplate.opsForList();
		Long size = opsForList.size(key);

		log.info("[缓存聊天信息]：" + size);

		if (size > CACHE_SIZE) {
			opsForList.rightPopAndLeftPush(key, msg.toJson());
		} else {
			opsForList.leftPush(key, msg.toJson());
		}

		redisTemplate.expire(key, RedisUtil.EXRP_MONTH, TimeUnit.SECONDS);
	}

	/** 清除缓存信息 */
	public void cleanCache(WebSockMsg msg, boolean hard) {

		if (hard) {

		} else {
			List<WebSockMsg> msgCache = getMsgCache(msg);
			if (msgCache == null || msgCache.isEmpty())
				return;
		}
		redisTemplate.delete(createKey(msg));
		chatLogService.updateChatLogUnReaded(msg.getSalesid(), msg.getFansid());

	}

	/** 获取未读信息 */
	public List<WebSockMsg> getMsgCache(WebSockMsg msg) {
		String key = createKey(msg);
		List<String> range = redisTemplate.opsForList().range(key, 1, -1);
		if (range.isEmpty()) {
			return null;
		}
		return range.stream().map(e -> WebSockMsg.fromJson(e)).collect(Collectors.toList());
	}

	/** 返回未读条数 */
	public Long unReadedSize(WebSockMsg msg) {
		String key = createKey(msg);
		return redisTemplate.opsForList().size(key);
	}

	@Override
	public boolean handleProcess(String openId, String content, String imageUrl) {

		Fans fans = fansService.getFansByMiniOpenid(openId);

		WebSockMsg msg = new WebSockMsg();
		if (!Strings.isNullOrEmpty(content)) {
			msg.setAsk(QQFaceUtil.regix(content));
		} else if (!Strings.isNullOrEmpty(imageUrl)) {
			msg.setReplytype(ChatLogReplyType.客户图片.getIndex());
			msg.setImgurl(imageUrl);
		}

		msg.setAsk(content);
		msg.setAsktime(new Date(System.currentTimeMillis()));

		if (fans != null) {
			Integer salesid = fans.getSalesid();
			msg.setFansid(fans.getId());
			msg.setAskfrom((salesid == null || salesid == 0) ? 2 : 1);
			msg.setLogo(Strings.isNullOrEmpty(fans.getLogo()) ? "" : fans.getLogo());
			msg.setNickname(Strings.isNullOrEmpty(fans.getNickname()) ? "" : fans.getNickname());

			int connected = isConnected(salesid);
			if (connected >= 0) {
				msg.setSalesid(connected);
				msg.setVankerid(connected);
				boolean checkChatStatus = checkChatStatus(connected, fans.getId());
				if (checkChatStatus) {
					recevice(msg);
				}
				return checkChatStatus;
			}
		}
		return false;
	}

	public int isConnected(Integer salesId) {
		Sales sales = salesService.getSales(salesId);
		if (salesId == null)
			return -1;
		Set<Integer> distinctRandomMembers = null;
		if (salesId == 0 || sales.getIsvanker() == null || sales.getIsvanker()) {
			BoundSetOperations<String, Integer> boundSetOps = redisTemplate2
					.boundSetOps(DvminiSocketService.KEY_VANKER);
			log.info("size=======================>{}" + boundSetOps.size());
			if (boundSetOps.size() > 0)
				return boundSetOps.randomMember();
			else
				return -1;
		} else {
			distinctRandomMembers = redisTemplate2.boundSetOps(DvminiSocketService.KEY_SALES)
					.distinctRandomMembers(redisTemplate.boundSetOps(KEY_SALES).size());
		}

		if (distinctRandomMembers == null || distinctRandomMembers.isEmpty()) {
			return -1;
		}

		for (Integer i : distinctRandomMembers) {
			if (salesId.equals(i)) {
				log.info("【socket通讯】 返回接待的销售salseId={}", i);
				return salesId;
			}
		}

		return -1;
	}

	@Override
	public boolean checkChatStatus(Integer salesId, Integer fansId) {
		return !Strings.isNullOrEmpty(
				redisTemplate.opsForValue().get(ChATSTATUS.concat("salesId-" + salesId + "@" + "fansId-" + fansId)));
	}

	@Override
	public void updateChatStatus(Integer salesId, Integer fansId) {
		redisTemplate.opsForValue().set(ChATSTATUS.concat("salesId-" + salesId + "@" + "fansId-" + fansId),
				DateUtil.getCurrentDateTime4Str(), 10, TimeUnit.MINUTES);
	}

	@Override
	public void removeChatStatus(Integer salesId, Integer fansId) {
		redisTemplate.delete(ChATSTATUS.concat("salesId-" + salesId + "@" + "fansId-" + fansId));
	}

}
